iT邦幫忙

DAY 17
4

Kuick Hands on Labs系列 第 17

Kuick Hands on Labs -- 17. 列表與分頁

  • 分享至 

  • xImage
  •  

承接上一篇分享,列表資料完成雛型之後,接著是建立分頁碼與列表連動。

分頁碼使用 Bootstrap 樣式,再作了小修改以呈現出 5 種按鈕(第一頁、上一頁、中間分頁碼、下一頁、最後一頁)。
Bootstrap 分頁樣式

Kuick 分頁樣式

Kuick 提供 Paginator 類別協助建立所需要的分頁參數,Paginator 建構式只需傳入「每頁資料筆數」、「目前資料頁碼」與「所有資料筆數」,就可以取得以下分頁參數:

public int Count { get; }                 // 資料筆數
public int FirstPageIndex { get; }        // 第一頁頁碼
public int LastPageIndex { get; }         // 最後一頁頁碼
public int NextPageIndex { get; }         // 下一頁頁碼
public int NextViewPortPageIndex { get; } // 下一頁區間頁碼
public int PageIndex { get; }             // 目前頁碼
public int PageRowCount { get; }          // 本頁資料筆數
public PageOne[] Pages { get; }           // 區間頁碼集合
public int PageSize { get; }              // 分頁資料筆數
public int PrePageIndex { get; }          // 前一頁頁碼
public int PreViewPortPageIndex { get; }  // 上一頁區間頁碼
public int RowFrom { get; }               // 本頁起始資料序次
public int RowTo { get; }                 // 本頁結束資料序次
public int ViewportSize { get; set; }     // 區間頁數

列表資料額外在所產生的 HTML 裡,加上幾個自定義的 attribute,這些資料將用於後續 Ajax 處理的參數來源:
1. table >> EntityName
table 加上 EntityName 屬性,載明資料來源。
2. tr >> KeyValue
每一筆資料 tr 加上 KeyValue 屬性,載明該筆資料主鍵。
3. td >> ColumnName
每一個欄位 td 加上 ColumnName 屬性,載明資料欄位名稱。

接下來直接將列表頁程式碼貼上,完整的範例網站將於10/30提供下載。

using System;
using System.Collections.Generic;
using System.Text;
using Kuick;
using Kuick.Data;
using Kuick.Labs.IronMan6;
using Kuick.Web;
 
public partial class entity_default : PageBase
{
	[RequestParameter]
	public string EntityName { get; set; }
 
	[RequestParameter]
	public int PageSize { get; set; }
 
	[RequestParameter]
	public int PageIndex { get; set; }
 
	protected override void OnPreRender(EventArgs e)
	{
		base.OnPreRender(e);
 
		PageSize = 2;
		PageIndex = Math.Max(PageIndex, 1);
	}
 
	// 顯示列表與分頁
	public string Render()
	{
		// 規格驗證
		IEntity schema = null;
		try {
			schema = EntityCache.Get(EntityName);
			if(null == schema) { return string.Empty; }
		} catch(Exception ex) {
			Logger.Error(ex, new Any("EntityName", EntityName));
			Response.Redirect("~/", true);
		}
 
		StringBuilder sb = new StringBuilder();
		BuildList(sb, schema);
		BuildPaginator(sb);
 
		return sb.ToString();
	}
 
	// 建立列表資料
	public void BuildList(StringBuilder sb, IEntity schema)
	{
		// 選取分頁資料集合
		List<IEntity> instances = BuildSql().Query();
 
 
		// table open tag
		sb.AppendFormat(
			"<table class=\"table table-bordered table-hover\" EntityName=\"{0}\">",
			EntityName
		);
 
		// thead
		sb.Append("<thead>");
		sb.Append("<tr>");
		sb.Append("<th class=\"ellipsis\">#</th>");
		foreach(var column in schema.Columns) {
			if(SkipField(column)) { continue; }
			sb.AppendFormat("<th class=\"ellipsis\">{0}</th>", column.Title);
		}
		sb.Append("</tr>");
		sb.Append("</thead>");
 
		// tbody
		int index = PageSize * (PageIndex - 1);
		sb.Append("<tbody>");
		if(instances.IsNullOrEmpty()) {
			sb.Append("<tr>");
			sb.AppendFormat(
				"<td colspan=\"{0}\">-- no data --</td>",
				DisplayFieldCount(schema) + 1
			);
			sb.Append("</tr>");
		} else {
			foreach(var instance in instances) {
				sb.AppendFormat("<tr KeyValue=\"{0}\">", instance.KeyValue);
				sb.AppendFormat("<td class=\"ellipsis\">{0}</td>", ++index);
				foreach(var column in schema.Columns) {
					if(SkipField(column)) { continue; }
					sb.AppendFormat(
						"<td class=\"ellipsis\" ColumnName=\"{0}\">{1}</td>",
						column.Spec.ColumnName,
						DisplayFieldValue(instance, column)
					);
				}
				sb.Append("</tr>");
			}
		}
		sb.Append("</tbody>");
 
		// table close tag
		sb.Append("</table>");
	}
 
	// 建立分頁資料
	public void BuildPaginator(StringBuilder sb)
	{
		Paginator paginator = new Paginator(
			PageSize, PageIndex, BuildSql().Count()
		);
		Anys parameters = new Anys();
		parameters.Add(IronMan6Constants.EntityName, EntityName);
 
		string url = WebTools.GetCurrentFullPath();
 
		Anys ps = new Anys();
		paginator.ViewportSize = 10;
 
		Anys anys = new Anys();
		if(!Checker.IsNull(parameters)) {
			anys.AddRange(parameters);
		}
 
		// PageSize
		if(!anys.Exists(IronMan6Constants.PageSize)) {
			anys.Add(new Any(
				IronMan6Constants.PageSize,
				paginator.PageSize
			));
		}
 
		// PageIndex
		anys.Remove(IronMan6Constants.PageIndex);
 
		sb.Append("<div class=\"text-center\">");
		sb.Append("<ul class=\"pagination\">");
 
		// FirstPage
		bool disabledFirst = PageIndex < 2;
		ps = BuildPaginatorParameter(anys, paginator.FirstPageIndex);
		sb.AppendFormat(
			"<li{0}><a href=\"{1}\">«</a></li>",
			disabledFirst ? " class=\"disabled\"" : string.Empty,
			WebTools.BuildQueryString(url, ps.ToArray())
		);
 
		// PrePageIndex
		bool disabledPre = PageIndex < 2;
		ps = BuildPaginatorParameter(anys, paginator.PrePageIndex);
		sb.AppendFormat(
			"<li{0}><a href=\"{1}\"><</a></li>",
			disabledPre ? " class=\"disabled\"" : string.Empty,
			WebTools.BuildQueryString(url, ps.ToArray())
		);
 
		// Viewport
		foreach(PageOne page in paginator.Pages) {
			bool active = page.PageIndex == paginator.PageIndex;
			ps = BuildPaginatorParameter(anys, page.PageIndex);
			sb.AppendFormat(
				"<li{0}><a href=\"{1}\">{2}</a></li>",
				active ? " class=\"active\"" : string.Empty,
				WebTools.BuildQueryString(url, ps.ToArray()),
				page.PageIndex
			);
		}
 
		// NextPageIndex
		bool disabledNext = PageIndex >= paginator.LastPageIndex;
		ps = BuildPaginatorParameter(anys, paginator.NextPageIndex);
		sb.AppendFormat(
			"<li{0}><a href=\"{1}\">></a>",
			disabledNext ? " class=\"disabled\"" : string.Empty,
			WebTools.BuildQueryString(url, ps.ToArray())
		);
 
		// LastPageIndex
		bool disabledLast = PageIndex >= paginator.LastPageIndex;
		ps = BuildPaginatorParameter(anys, paginator.LastPageIndex);
		sb.AppendFormat(
			"<li{0}><a href=\"{1}\">»</a>",
			disabledLast ? " class=\"disabled\"" : string.Empty,
			WebTools.BuildQueryString(url, ps.ToArray())
		);
 
		sb.Append("</ul>");
		sb.Append("</div>");
	}
 
	// 建立分頁參數
	private Anys BuildPaginatorParameter(Anys ps, int index)
	{
		Anys anys = new Anys(ps.ToArray());
		anys.Add(new Any(IronMan6Constants.PageIndex, index));
		return anys;
	}
 
	// 建立查詢Sql物件
	private Sql BuildSql()
	{
		Sql sql = Entity
			.Sql(EntityName)
			.Paging(PageSize, PageIndex);
		return sql;
	}
 
 
	// 顯示欄位數目
	private int DisplayFieldCount(IEntity schema)
	{
		int count = 0;
		foreach(var column in schema.Columns) {
			if(!SkipField(column)) { count++; }
		}
		return count;
	}
 
	// 隱藏欄位判斷
	private bool SkipField(Column column)
	{
		// 加密欄位
		if(null != column.Encryption) { return true; }
 
		// 系統內建欄位
		if(column.Visual.SystemColumn) { return true; }
 
		// 其他欄位皆顯示
		return false;
	}
 
 
	// 重組欄位值
	private string DisplayFieldValue(IEntity instance, Column column)
	{
		// null 欄位直接回傳空定串
		bool isNull = instance.IsNullCheck(column.Spec.ColumnName);
		if(isNull) { return string.Empty; }
 
		// 取值
		object value = instance.GetValue(column);
 
		if(
			null != column.Refer.Type
			&&
			column.Spec.DbType != SqlDataType.Enum
			&&
			column.Spec.DbType != SqlDataType.Bit) {
			// 以 PK 參照其他 Entity
 
			// 從 Entity 快取取出參照定義
			IEntity[] refSchemas = EntityCache.Get(column.Refer.Type);
			if(refSchemas.IsNullOrEmpty()) {
				return string.Empty;
			} else {
				IEntity one = Entity.Get(
					refSchemas[0].EntityName,
					value.ToString()
				);
				if(null == one) {
					return value.ToString();
				} else {
					// 回傳參照資料 TitleValue 屬性
					return one.TitleValue;
				}
			}
 
		} else if(column.IsBoolean) {
			// 布林值:使用圖型顯示
			bool b = (bool)value;
			return b
				? "<span class=\"glyphicon glyphicon-ok\"></span>"
				: string.Empty;
 
		} else if(column.IsNumber) {
			// 數值
			return value.ToString();
 
		} else if(column.IsDateTime) {
			// 日期
			DateTime d = (DateTime)value;
			if(column.Visual.Input == VisualInput.Date) {
				// 只顯示年月日 (yyyy-MM-dd)
				return d.yyyyMMdd();
			} else {
				// 顯示時戳 (yyyy-MM-dd hh:mm:ss)
				return d.yyyyMMddHHmmss();
			}
 
		} else if(column.IsEnum) {
			// 列舉
 
			// 從列舉快取取出定義
			EnumReference ef = EnumCache.Get(column.Property.PropertyType);
			if(null == ef) { return string.Empty; }
 
			// 查詢目前列舉項目資訊
			EnumItem ei = ef.Get(value.ToString());
			if(null == ei) { return string.Empty; }
 
			// 顯示該列舉項目 DescriptionAttribute 定義值
			return ei.Title;
 
		} else {
			// 一般
			return value.ToString();
		}
	}
}

上一篇
Kuick Hands on Labs -- 16. 優化列表資料
下一篇
Kuick Hands on Labs -- 18. 資料新增表單
系列文
Kuick Hands on Labs30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

我要留言

立即登入留言